﻿namespace CN2P.ServiceModel.ServiceClients
{
    using System.Net;
    using System.Text;
    using Newtonsoft.Json;

    public class BaseServiceClient
    {

        protected readonly string _baseUrl;

        protected BaseServiceClient(string baseUrl)
        {
            this._baseUrl = baseUrl;
        }

        protected ServiceResponse ExecuteGet(string url)
        {
            return this.Execute("GET", url);
        }

        protected ServiceResponse<T> ExecuteGet<T>(string url)
        {
            return this.Execute<T>("GET", url);
        }

        protected ServiceResponse ExecutePost(string url, string data)
        {
            return this.ExecutePost(url, Encoding.UTF8.GetBytes(data));
        }

        protected ServiceResponse ExecutePost(string url, byte[] data)
        {
            return this.Execute("POST", url, data);
        }

        protected ServiceResponse ExecutePut(string url, string data)
        {
            return this.ExecutePut(url, Encoding.UTF8.GetBytes(data));
        }

        protected ServiceResponse ExecutePut(string url, byte[] data)
        {
            return this.Execute("PUT", url, data);
        }

        protected ServiceResponse ExecuteDelete(string url)
        {
            return this.Execute("DELETE", url);
        }

        private ServiceResponse<T> Execute<T>(string method, string url, byte[] data = null)
        {
            var raw = this.Execute(method, url, data);
            return ServiceResponse<T>.From(raw);
        }

        private ServiceResponse Execute(string method, string url, byte[] data = null)
        {
            var request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = method;

            if (data != null)
            {
                request.ContentLength = data.Length;
                request.ContentType = "application/json";
                var requestStream = request.GetRequestStream();
                requestStream.Write(data, 0, data.Length);
            }

            try
            {
                var response = (HttpWebResponse)request.GetResponse();
                return ServiceResponse.From(response);
            }
            catch (WebException exc)
            {
                var response = (HttpWebResponse)exc.Response;
                return ServiceResponse.From(response);
            }
        }

        protected void ValidateResponse(ServiceResponse response, HttpStatusCode expectedCode)
        {
            if (response.Code != expectedCode)
            {
                throw new UnexpectedServiceResponseException(expectedCode, response.Code);
            }
        }

        protected void ValidateResponse<T>(ServiceResponse<T> response, HttpStatusCode expectedCode)
        {
            if (response.Code != expectedCode)
            {
                throw new UnexpectedServiceResponseException(expectedCode, response.Code);
            }
        }

        protected string Serialize<T>(T obj)
        {
            return JsonConvert.SerializeObject(obj);
        }
    }
}
